#pragma once

#include <boost/noncopyable.hpp>
#include <boostext/exception.hpp>
#include <boost/smart_ptr.hpp>

#include "exports.hpp"
#include "Plugin.h"




class plugin_not_loaded : public boostext::exception
{
public:

	plugin_not_loaded(const char* what)
		: boostext::exception(what)
	{}
};
///////////////////////////////////////////////////////////////////////////////////////////////////




/**
 * This class serves as a container between an actual plugin that implements the AbstractPlugin interface
 * and the rest of the application. The plugin loader is responsible for loading a plugin (ie. the library)
 * and creating all available interfaces (one plugin is allowed to offer multiple interfaces at once).
 *
 * It is important that before destroying a plugin loader, all references to the plugins of that loader
 * should be released, otherwise the plugin cannot be unloaded.
 */
class CRAWLER_API PluginLoader
	: public boost::noncopyable
{
public:

	typedef Plugin::Ptr (*CreateFunction)(std::size_t);
	typedef std::size_t (*NumberFunction)();

	typedef boost::shared_ptr<PluginLoader>         Ptr;
	typedef boost::shared_ptr<const PluginLoader>   const_Ptr;

	typedef QList<Plugin::Ptr>        Plugins;
	typedef Plugins::iterator         iterator;
	typedef Plugins::const_iterator   const_iterator;

private:

	QLibrary   m_library;
	Plugins    m_plugins;

public:

	PluginLoader(QString fileName);
	~PluginLoader();

	bool canUnload() const;


	std::size_t numPlugins() const;
	iterator begin();
	iterator end();
	const_iterator begin() const;
	const_iterator end() const;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
